import type MountableFileSystem from "browserfs/dist/node/backend/MountableFileSystem";
import type {
  BFSCallback,
  FileSystem,
} from "browserfs/dist/node/core/file_system";
import type Stats from "browserfs/dist/node/core/node_fs_stats";
import { useMemo } from "react";
import { EMPTY_BUFFER } from "utils/constants";

export type AsyncFS = {
  exists: (path: string) => Promise<boolean>;
  mkdir: (path: string, overwrite?: boolean) => Promise<boolean>;
  readFile: (path: string) => Promise<Buffer>;
  readdir: (path: string) => Promise<string[]>;
  rename: (oldPath: string, newPath: string) => Promise<boolean>;
  rmdir: (path: string) => Promise<boolean>;
  stat: (path: string) => Promise<Stats>;
  unlink: (path: string) => Promise<boolean>;
  writeFile: (
    path: string,
    data: Buffer | string,
    overwrite?: boolean
  ) => Promise<boolean>;
};

type IFileSystemAccess = {
  FileSystem: {
    FileSystemAccess: {
      Create: (
        opts: { handle: FileSystemDirectoryHandle },
        cb: BFSCallback<FileSystem>
      ) => void;
    };
  };
};

export type RootFileSystem = Omit<
  MountableFileSystem,
  "mntMap" | "mountList"
> & {
  mntMap: Record<
    string,
    {
      data: Buffer;
      getName: () => string;
    }
  >;
  mountList: string[];
};

type AsyncFSModule = AsyncFS;

const useAsyncFs = (): AsyncFSModule => {
  const asyncFs: AsyncFS = useMemo(
    () => ({
      exists: (path) =>
        new Promise((resolve) => {
          console.log("async fs exists", path);
          resolve(false);
          // fs?.exists(path, resolve);
        }),
      mkdir: (path, overwrite = false) =>
        new Promise((resolve, reject) => {
          console.log("async fs mkdir", path, overwrite);
          resolve(false);
          // fs?.mkdir(path, { flag: overwrite ? "w" : "wx" }, (error) =>
          //   error ? reject(error) : resolve(true)
          // );
        }),
      readFile: (path) =>
        new Promise((resolve, reject) => {
          console.log("async fs readFile", path);
          resolve(EMPTY_BUFFER);
          // fs?.readFile(path, (error, data = EMPTY_BUFFER) => {
          //   if (!error) return resolve(data);

          //   if (error.code === "EISDIR" && rootFs?.mntMap[path]?.data) {
          //     return resolve(rootFs.mntMap[path].data);
          //   }

          //   return reject(error);
          // });
        }),
      readdir: (path) =>
        new Promise((resolve, reject) => {
          console.log("async fs readdir", path);
          resolve([]);
          // fs?.readdir(path, (error, data = []) =>
          //   error ? reject(error) : resolve(data)
          // );
        }),
      rename: (oldPath, newPath) =>
        new Promise((resolve, reject) => {
          console.log("async fs rename", oldPath, newPath);
          resolve(false);
          // fs?.rename(oldPath, newPath, (renameError) => {
          //   if (!renameError) {
          //     resolve(true);
          //   } else if (renameError.code === "ENOTSUP") {
          //     fs.stat(oldPath, (_statsError, stats = {} as Stats) => {
          //       if (stats.isDirectory()) {
          //         reject();
          //       } else {
          //         fs.readFile(oldPath, (readError, data) =>
          //           fs.writeFile(newPath, data, (writeError) =>
          //             readError || writeError
          //               ? reject(readError || writeError)
          //               : resolve(false)
          //           )
          //         );
          //       }
          //     });
          //   } else if (renameError.code === "EISDIR") {
          //     rootFs?.umount(oldPath);
          //     asyncFs.rename(oldPath, newPath).then(resolve, reject);
          //   } else {
          //     reject(renameError);
          //   }
          // });
        }),
      rmdir: (path) =>
        new Promise((resolve, reject) => {
          console.log("async fs rmdir", path);
          resolve(true);
          // fs?.rmdir(path, (error) => (error ? reject(error) : resolve(true)));
        }),
      stat: (path) =>
        new Promise((resolve, reject) => {
          console.log("async fs stat", path);
          resolve({} as Stats);
          // fs?.stat(path, (error, stats = {} as Stats) =>
          //   error ? reject(error) : resolve(stats)
          // );
        }),
      unlink: (path) =>
        new Promise((resolve, reject) => {
          console.log("async fs unlink", path);
          resolve(true);
          // fs?.unlink(path, (error) => (error ? reject(error) : resolve(true)));
        }),
      writeFile: (path, data, overwrite = false) =>
        new Promise((resolve, reject) => {
          console.log("async fs writeFile", path, data, overwrite);
          resolve(true);
          // fs?.writeFile(path, data, { flag: overwrite ? "w" : "wx" }, (error) =>
          //   error && (!overwrite || error.code !== "EEXIST")
          //     ? reject(error)
          //     : resolve(!error)
          // );
        }),
    }),
    []
  );

  return asyncFs;
};

export default useAsyncFs;
